package cn.sunxyz.core.bean;

import cn.sunxyz.common.utils.StringUtil;
import cn.sunxyz.common.falut.InitializationException;
import cn.sunxyz.core.bean.annotation.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by yangrd on 2017/5/19.
 */
public class BeanContext {

    /**
     * Bean Map（Bean 类 => Bean 实例）
     */
    private static final Map<Class<?>, Object> beanMap = new HashMap<>();

    /**
     * Class Map（Bean 名称 => Bean 类）
     */
    private static final Map<String, Class<?>> classMap = new HashMap<>();

    static void initBean(ClassContainer classContainer) {
        try {
            // 获取应用包路径下所有带有 Component 注解的类
            List<Class<?>> classList = classContainer.listClassByAnnotation(Component.class);
            for (Class<?> cls : classList) {
                // 将 Bean 实例放入 Bean Map 中（键为 Bean 类，值为 Bean 实例）=> 实例创建委托给插件
                putBean(cls, null);
                Component component = cls.getAnnotation(Component.class);
                String beanName = component.value();
                // 将 Bean 类 放入 Class Map 中（键为 Class 类名 或 用户定义的名称 ，值为 Bean 类）
                if (StringUtil.isNotEmpty(beanName)) {
                    putClass(StringUtil.firstToLower(cls.getSimpleName()), cls);
                } else {
                    putClass(beanName, cls);
                }
            }
        } catch (Exception e) {
            throw new InitializationException("初始化 BeanContext 出错！", e);
        }
    }

    public static void putClass(String beanName, Class<?> clazz) {
        classMap.put(beanName, clazz);
    }

    public static void putBean(Class<?> clazz, Object target) {
        beanMap.put(clazz, target);
    }


    /**
     * 获取 Bean 实例
     */
    public static <T> T getBean(String beanName) {
        return (T) getBean(getClass(beanName));
    }

    /**
     * 获取 Bean 实例
     */
    public static <T> T getBean(Class<?> cls) {
        checkClass(cls);
        return (T) beanMap.get(cls);
    }

    public static Map<Class<?>, Object> getBeanMap() {
        return beanMap;
    }

    public static Map<String, Class<?>> getClassMap() {
        return classMap;
    }

    private static Class<?> getClass(String beanName) {
        checkBeanName(beanName);
        return classMap.get(beanName);
    }

    private static void checkBeanName(String beanName) {
        if (!classMap.containsKey(beanName)) {
            throw new RuntimeException("没有找到" + beanName);
        }
    }

    private static void checkClass(Class<?> cls) {
        if (!beanMap.containsKey(cls)) {
            throw new RuntimeException("无法根据类名:" + cls + "获取实例！请检测" + cls + "是否注册");
        }
    }
}
